//
// Created by LiuYou on 2021/7/2.
//

#include "MySemaphore.hpp"
#include <pthread.h>
#include <malloc.h>

struct MySem {
    int value;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
};

mysem_t* mySemInit(int initVal) {
    struct MySem* me = static_cast<MySem*>(malloc(sizeof(*me)));
    if (me == nullptr) {
        return nullptr;
    }
    me->value = initVal;
    pthread_mutex_init(&me->mutex, nullptr);
    pthread_cond_init(&me->cond, nullptr);


    return me;
}

int mySemAdd(mysem_t* ptr, int n) {
    struct MySem* me = static_cast<MySem*>(ptr);
    pthread_mutex_lock(&me->mutex);

    me->value += n;
    pthread_cond_broadcast(&me->cond);
    pthread_mutex_unlock(&me->mutex);

    return n;
}

int mySemSub(mysem_t* ptr, int n) {
    struct MySem* me = static_cast<MySem*>(ptr);
    pthread_mutex_lock(&me->mutex);

    while (me->value < n) {
        pthread_cond_wait(&me->cond, &me->mutex);
    }
    me->value -= n;

    pthread_mutex_unlock(&me->mutex);
    return n;
}

int mySemDestroy(mysem_t* ptr) {
    struct MySem* me = static_cast<MySem*>(ptr);

    pthread_mutex_destroy(&me->mutex);
    pthread_cond_destroy(&me->cond);

    free(me);
    return 0;
}
